package org.psyduck.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import org.psyduck.common.utils.FileUtils;
import org.psyduck.common.utils.Global;
import org.psyduck.common.utils.OSSUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class OSSSdk implements OSSUtils {

  @Value("${upload.oss.endpoint}")
  public String ENDPOINT;

  @Value("${upload.oss.access-key-id}")
  public String ACCESS_KEY_ID;

  @Value("${upload.oss.access-key-secret}")
  public String ACCESS_KEY_SECRET;

  @Value("${upload.oss.bucket-name}")
  public String BUCKET_NAME;

  @Value("${upload.oss.transport-protocol:https}")
  public String OSS_TRANSPORT_PROTOCOL;

  /**
   * 
   * @Title: getOSSClient 
   * @Description: 获取oss客户端 
   * @return OSSClient oss客户端 
   * @throws
   */
  public OSSClient getOSSClient() {
    return new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
  }

  /**
   * 
   * @Title: uploadByNetworkStream 
   * @Description: 通过网络流上传文件
   * @param ossClient 	oss客户端 
   * @param url 			URL 
   * @param bucketName 	bucket名称 
   * @param objectName 	上传文件目录和（包括文件名）例如“test/index.html” 
   * @return void 		返回类型
   * @throws
   */
  public static void uploadByNetworkStream(OSSClient ossClient, URL url, String bucketName, String objectName) {
    try {
      InputStream inputStream = url.openStream();
      ossClient.putObject(bucketName, objectName, inputStream);
      ossClient.shutdown();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }
  }

  /**
   * 
   * @Title: uploadByInputStream 
   * @Description: 通过输入流上传文件
   * @param ossClient 	oss客户端 
   * @param inputStream 	输入流 
   * @param bucketName 	bucket名称
   * @param objectName 	上传文件目录和（包括文件名） 例如“test/a.jpg” 
   * @return void 		返回类型 
   * @throws
   */
  public static void uploadByInputStream(OSSClient ossClient, InputStream inputStream, String bucketName, String objectName) {
    try {
      ossClient.putObject(bucketName, objectName, inputStream);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }
  }

  /**
   * 
   * @Title: uploadByFile 
   * @Description: 通过file上传文件 
   * @param ossClient 	oss客户端 
   * @param file 			上传的文件 
   * @param bucketName 	bucket名称
   * @param objectName 	上传文件目录和（包括文件名） 例如“test/a.jpg” 
   * @return void 		返回类型
   * @throws
   */
  public static void uploadByFile(OSSClient ossClient, File file, String bucketName, String objectName) {
    try {
      ossClient.putObject(bucketName, objectName, file);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }
  }

  /**
   * 
      * @Title: deleteFile  
      * @Description: 根据key删除oss服务器上的文件
      * @param key    		文件路径/名称，例如“test/a.txt”
      * @return void    		返回类型  
      * @throws
   */
  public void deleteFile(String key) {
    getOSSClient().deleteObject(BUCKET_NAME, key);
  }

  /**
   * 
   * @Title: getInputStreamByOSS 
   * @Description:根据key获取服务器上的文件的输入流 
   * @param ossClient 	oss客户端  
   * @param bucketName 	bucket名称 
   * @param key 			文件路径和名称 
   * @return InputStream 	文件输入流
   * @throws
   */
  public static InputStream getInputStreamByOSS(OSSClient ossClient, String bucketName, String key) {
    InputStream content = null;
    try {
      OSSObject ossObj = ossClient.getObject(bucketName, key);
      content = ossObj.getObjectContent();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return content;
  }

  /**
   * 
      * @Title: queryAllObject  
      * @Description: 查询某个bucket里面的所有文件
      * @param ossClient		oss客户端
      * @param bucketName		bucket名称
      * @return List<String>  文件路径和大小集合  
      * @throws
   */
  public static List<String> queryAllObject(OSSClient ossClient, String bucketName) {
    List<String> results = new ArrayList<String>();
    try {
      // ossClient.listObjects返回ObjectListing实例，包含此次listObject请求的返回结果。
      ObjectListing objectListing = ossClient.listObjects(bucketName);
      // objectListing.getObjectSummaries获取所有文件的描述信息。
      for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
        results.add(" - " + objectSummary.getKey() + "  " + "(size = " + objectSummary.getSize() + ")");
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }
    return results;
  }

  public static Map<String,String> getImageSize(InputStream inputStream){
    HashMap<String, String> map = new HashMap<>();
    try {
        BufferedImage bufferedImage = ImageIO.read(inputStream); // 通过MultipartFile得到InputStream，从而得到BufferedImage
        if (bufferedImage == null) {
            // 证明上传的文件不是图片，获取图片流失败，不进行下面的操作
        }
        Integer width = bufferedImage.getWidth();
        Integer height = bufferedImage.getHeight();
        map.put("width", width + "");
        map.put("height", height + "");
       // 省略逻辑判断
    } catch (Exception e) {
        // 省略异常操作
    }
    return map;
  }

  /**
   * 上传文件到oss
   */
  @Override
  public Map<String, String> uploadFileToOss(String originalFilename, byte[] bytes, InputStream inputStream) {
    Map<String, String> fileAttr = FileUtils.createFileAttr(originalFilename);
    try {
      String filePath = fileAttr.get("filePath");
      uploadByInputStream(getOSSClient(), new ByteArrayInputStream(bytes), BUCKET_NAME, filePath);
      Map<String, String> map = getImageSize(inputStream);
      map.put("url", filePath);
      return map;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public boolean isDefault() {
    return false;
  }

}